/**
 * Created by DevilsEyes on 2016/2/13.
 * ================================
 *             进程管理
 * ================================
 *
 */
'use strict';

var init = require('./init.js');
var Captor = require('./captor/main.js');
var $doc = require('../model/doc.js');
var $stats = require('../model/stats.js');

const delay = 30,//百度请求延迟
    processBlock = 1000,//进程阻塞最大时长
    processMax = 10,//进程数量
    registerMax = 20,//缓存池最大数量
    retryTimes = 5;//重试次数

var _state_ = Symbol('state');
var _type_ = Symbol('type');

//定义一个进程
class Process {

    constructor(id, type) {
        this.type = type || 0;
        this.timer = null;
        //type: 进程类型
        //0 -> 标准
        //1 -> 百度搜索

        this.id = id;
        this.target = '';
        this.avaliable = true;
    }

    capt(doc) {
        this.avaliable = false;
        this.target = doc.id;
        this.timer = setTimeout(()=>{
            doc.status = -1;
            this.timer = null;
        },processBlock);
        return new Promise((done, fail)=> {
            new Captor(doc)
                .start()
                .request_done(()=>{
                    clearTimeout(this.timer);
                })
                .update_done(()=> {
                    let docId = this.target;
                    if (this.type == 0) {
                        this.avaliable = true;
                        this.target = null;
                        done(docId);
                    } else {
                        setTimeout(()=> {
                            this.avaliable = true;
                            this.target = null;
                            done(docId);
                        }, delay);
                    }
                })
                .interrupt(()=> {
                    let docId = this.target;
                    this.avaliable = true;
                    this.target = null;
                    fail(docId);
                });
        });
    }
}

//定义一个寄存器 - 单例
var Register = {
    init(stats){
        this.list = new Map();

        this.status = 'empty';
        //三个状态
        //loading
        //empty
        //working

        this.success = stats.success;
        this.wait = stats.wait;
        this.total = stats.total;
        this.max = stats.max;
        this.last = stats.last;

        console.log('======================');
        console.log('Register init complete!');

        return this;

    },

    refresh(){
        return new Promise((done, fail)=> {

            if (this.status === 'loading')return fail();
            this.status = 'loading';

            $doc.getSome(registerMax)
                .exec((err, docs)=> {

                    docs.forEach((doc, i)=> {
                        if (Register.list.has(doc.id)) {
                            return;
                        }

                        doc[_state_] = 0;
                        if (doc.link.match(/www\.baidu\.com/i) != null) {
                            doc[_type_] = 1;
                        } else {
                            doc[_type_] = 0;
                        }
                        Register.list.set(doc.id, doc);
                    });

                    Register.status = Register.list.length == 0 ? 'empty' : 'working';

                    //console.log('======================');
                    //console.log('Register refresh complete!');
                    //console.log(Register);

                    done();
                })

        })
    },

    getDoc(type){
        var res = null;
        for (var doc of [...this.list.values()]) {
            if (doc[_state_] === 0 && doc[_type_] == type) {
                doc[_state_] = 1;
                res = doc;
                break;
            }
        }
        if (res === null) {
            for (doc of [...this.list.values()]) {
                if (doc[_state_] === 0) {
                    return null;
                }
            }
            throw '寄存器的库存都用光啦!';
        } else {
            return res;
        }
    },

    popDoc(id){
        this.list.delete(id);
    }
};

//管理器
var Manager = {
    processList: new Map(),
    init(){

        //普通线程
        for (let i = 0; i < processMax; i++) {
            Manager.processList.set(i, new Process(i));
        }

        //百度专用线程
        Manager.processList.set(processMax, new Process(processMax, 1));

        setInterval(Manager.diliver, 2000);
        Register.refresh()
            .then(()=> {
                Manager.diliver();
            });

        console.log('======================');
        console.log('Manager init complete!');

        return this;
    },
    diliver(){
        Manager.processList.forEach((pro, pro_id)=> {
            if (pro.avaliable) {
                var doc;
                try {
                    doc = Register.getDoc(pro.type);
                } catch (e) {
                    Register.refresh()
                        .then(()=> {
                            Manager.diliver();
                        });
                    return;
                }
                if (doc) {
                    pro.capt(doc)
                        .then(id=> {
                            Register.popDoc(id);
                            Manager.diliver();
                        });
                }
            }
        })
    }
};

init.done((stats) => {
    Register.init(stats);
    Manager.init();
    console.log('init.done()');

});

var countor = {
    retry: retryTimes,
    init(){
        setInterval(countor.count, 2000);
    },
    count(){

    }
};

module.exports = {
    watch(){
        return {

            Register: {
                list: [...Register.list.values()]
            },
            Manager: {
                list: [...Manager.processList.values()]
            }

        }
    }
};